package repository

import (
	"context"
	"errors"

	"gorm.io/gorm"

	"BookStack/internal/domain/book"
)

// bookRepository 书籍仓储实现
type bookRepository struct {
	db *gorm.DB
}

// NewBookRepository 创建书籍仓储
func NewBookRepository(db *gorm.DB) book.BookRepository {
	return &bookRepository{
		db: db,
	}
}

// Create 创建书籍
func (r *bookRepository) Create(ctx context.Context, b *book.Book) error {
	return r.db.WithContext(ctx).Create(b).Error
}

// GetByID 通过ID获取书籍
func (r *bookRepository) GetByID(ctx context.Context, id uint) (*book.Book, error) {
	var b book.Book
	if err := r.db.WithContext(ctx).First(&b, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &b, nil
}

// GetBySlug 通过Slug获取书籍
func (r *bookRepository) GetBySlug(ctx context.Context, slug string) (*book.Book, error) {
	var b book.Book
	if err := r.db.WithContext(ctx).Where("slug = ?", slug).First(&b).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &b, nil
}

// Update 更新书籍
func (r *bookRepository) Update(ctx context.Context, b *book.Book) error {
	return r.db.WithContext(ctx).Save(b).Error
}

// Delete 删除书籍
func (r *bookRepository) Delete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Delete(&book.Book{}, id).Error
}

// List 获取书籍列表
func (r *bookRepository) List(ctx context.Context, offset, limit int, filters map[string]interface{}) ([]*book.Book, int64, error) {
	var books []*book.Book
	var total int64
	query := r.db.WithContext(ctx).Model(&book.Book{})

	// 应用过滤条件
	if filters != nil {
		for key, value := range filters {
			query = query.Where(key, value)
		}
	}

	// 不包含已删除记录
	query = query.Where("deleted_at IS NULL")

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Order("created_at DESC").Find(&books).Error; err != nil {
		return nil, 0, err
	}

	return books, total, nil
}

// ListByCategory 获取指定分类的书籍列表
func (r *bookRepository) ListByCategory(ctx context.Context, categoryID uint, offset, limit int) ([]*book.Book, int64, error) {
	var books []*book.Book
	var total int64
	query := r.db.WithContext(ctx).Model(&book.Book{}).Where("category_id = ? AND deleted_at IS NULL", categoryID)

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Order("created_at DESC").Find(&books).Error; err != nil {
		return nil, 0, err
	}

	return books, total, nil
}

// ListByRecommended 获取推荐书籍列表
func (r *bookRepository) ListByRecommended(ctx context.Context, recommended int, offset, limit int) ([]*book.Book, int64, error) {
	var books []*book.Book
	var total int64
	query := r.db.WithContext(ctx).Model(&book.Book{}).Where("recommended = ? AND deleted_at IS NULL", recommended)

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Order("created_at DESC").Find(&books).Error; err != nil {
		return nil, 0, err
	}

	return books, total, nil
}

// Search 搜索书籍
func (r *bookRepository) Search(ctx context.Context, keyword string, offset, limit int) ([]*book.Book, int64, error) {
	var books []*book.Book
	var total int64
	query := r.db.WithContext(ctx).Model(&book.Book{}).
		Where("deleted_at IS NULL").
		Where("title LIKE ? OR author LIKE ? OR description LIKE ?", "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Order("created_at DESC").Find(&books).Error; err != nil {
		return nil, 0, err
	}

	return books, total, nil
}

// ListSoftDeleted 获取已软删除的书籍列表
func (r *bookRepository) ListSoftDeleted(ctx context.Context, offset, limit int) ([]*book.Book, int64, error) {
	var books []*book.Book
	var total int64
	query := r.db.WithContext(ctx).Model(&book.Book{}).Unscoped().Where("deleted_at IS NOT NULL")

	// 查询总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	if err := query.Offset(offset).Limit(limit).Order("deleted_at DESC").Find(&books).Error; err != nil {
		return nil, 0, err
	}

	return books, total, nil
}

// GetSoftDeletedByID 通过ID获取已软删除的书籍
func (r *bookRepository) GetSoftDeletedByID(ctx context.Context, id uint) (*book.Book, error) {
	var b book.Book
	if err := r.db.WithContext(ctx).Unscoped().Where("id = ? AND deleted_at IS NOT NULL", id).First(&b).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &b, nil
}

// Restore 恢复已软删除的书籍
func (r *bookRepository) Restore(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Unscoped().Model(&book.Book{}).Where("id = ?", id).Update("deleted_at", nil).Error
}

// HardDelete 硬删除书籍
func (r *bookRepository) HardDelete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Unscoped().Delete(&book.Book{}, id).Error
}

// CheckSlugExists 检查slug是否存在
func (r *bookRepository) CheckSlugExists(ctx context.Context, slug string, excludeID uint) (bool, error) {
	var count int64
	query := r.db.WithContext(ctx).Model(&book.Book{}).Where("slug = ?", slug)
	if excludeID > 0 {
		query = query.Where("id != ?", excludeID)
	}
	if err := query.Count(&count).Error; err != nil {
		return false, err
	}
	return count > 0, nil
}

// CountByCategoryID 统计分类下的书籍数量
func (r *bookRepository) CountByCategoryID(ctx context.Context, categoryID uint) (int64, error) {
	var count int64
	if err := r.db.WithContext(ctx).Model(&book.Book{}).Where("category_id = ? AND deleted_at IS NULL", categoryID).Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}
